package gridy.geneticoperations;

import gridy.algorithm.Individual;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class SBXRecombination implements Recombination {
    
    private double eta;
    private Random random;

    public SBXRecombination() {
        random = new Random();
    }
    
    public SBXRecombination(Double eta) {
        this();
        setEta(eta);
    }
    
    public void setEta(double eta) {
        this.eta = eta;
    }

    @Override
    public List<Individual> recombine(Individual ind1, Individual ind2) {
     
        Individual child1 = ind1.duplicate();
        Individual child2 = ind2.duplicate();

        for (int i = 0; i < ind1.getGenesNum(); i++) {
            double bq, u = random.nextDouble();
            if (u <= 0.5) {
                bq = Math.pow(2.0 * u, 1.0 / (eta + 1.0));
            } else {
                bq = Math.pow(1 / (2 * (1 - u)), 1.0 / (eta + 1.0));
            }
            child1.setGene(i, 0.5 * (((1.0 + bq) * ind1.getGene(i)) + (1.0 - bq) * ind2.getGene(i)));
            child2.setGene(i, 0.5 * (((1.0 - bq) * ind1.getGene(i)) + (1.0 + bq) * ind2.getGene(i)));
        }

        List<Individual> result = new LinkedList<Individual>();

        child1.normalizeGenes();
        child2.normalizeGenes();
        
        result.add(child1);
        result.add(child2);
        
        return result;
    }

}
